home *** CD-ROM | disk | FTP | other *** search
- /*
- FILENAME
- CustomBufferingAndIO.c
-
- DESCRIPTION
- Contains code that shows how to implement custom buffering and
- non-standard communications code in a QuickDraw GX printer
- driver. In this code, we write everything to disk (through our
- own buffers) as an extended version 2 PICT file.
-
- COPYRIGHT
- Copyright © 1995 Apple Computer, Inc.
- All rights reserved.
-
- Modification history
- 05/03/95 - Dave Hersey - Version 1.0.1 fixes the following bugs
- in this file.
-
- * endPict opcodes not always word aligned
- * current buffer not being reset on flush
- * gxWriteData override could not handle a
- simple flush by passing a nil data or
- length parameter.
- * gxFinishSendPage, gxCloseConnection, and
- gxCleanupOpenConnection overrides were
- doing work before forwarding their
- messages which should have been done after
- the forwards.
-
- 01/14/95 - Dave Hersey - Spawned.
-
- NOTE: Relevant goodies are listed in MPW's "Mark" menu.
-
- */
-
- #include "CommonDefines.h"
-
-
- /* -----------------------------------------------------------------------
-
- SD_OpenConnection is an override for gxOpenConnection. In this routine
- we allocate our custom buffer structures and forward the message to the
- default gxOpenConnection handler. Since we specify customIO in our
- 'iobm' resource, no connection is actually opened.
-
- ----------------------------------------------------------------------- */
-
- OSErr SD_OpenConnection()
- {
- OSErr anErr;
-
- // Create our buffers, then forward the message.
-
- anErr = CreateBuffers();
-
- if (!anErr)
- anErr = Forward_GXOpenConnection();
- else
- GXCleanupOpenConnection();
-
- return anErr;
- }
-
-
- /* -----------------------------------------------------------------------
-
- SD_CloseConnection is an override for gxCloseConnection. In this
- routine we forward the message to the default gxCloseConnection
- handler and dispose of our custom buffer structures.
-
- ----------------------------------------------------------------------- */
-
- OSErr SD_CloseConnection()
- {
- OSErr anErr;
-
- // Forward the message and dispose of our buffers.
-
- anErr = Forward_GXCloseConnection();
- DisposeBuffers();
-
- return anErr;
- }
-
-
- /* -----------------------------------------------------------------------
-
- SD_CleanupOpenConnection is an override for gxCleanupOpenConnection.
- In this routine we forward the message and dispose of our data
- structures that might have been allocated before we got an error in
- our gxOpenConnection code.
-
- ----------------------------------------------------------------------- */
-
- void SD_CleanupOpenConnection()
- {
- // Forward the message and dispose of our buffers (if any).
-
- Forward_GXCleanupOpenConnection();
- DisposeBuffers();
- }
-
-
- /* -----------------------------------------------------------------------
-
- SD_BufferData is an override for the gxBufferData message. To support
- our custom buffering code, we perform a total override of this message,
- fill up the next available buffer with the data. We'll store data and,
- if necessary, flush buffers until all of the passed data has been
- processed.
-
- ----------------------------------------------------------------------- */
-
- OSErr SD_BufferData(Ptr data, long length, long bufferOptions) // only override for custom buffering
- {
- OSErr anErr = noErr;
- register char *pData = data;
- register BufferEntryPtr buffPtr;
- short idx, curBuff;
- Boolean foundAFreeBuffer;
- long dataLeftToStore = length;
- register BufferGroupHdl buffGrpHdl = (BufferGroupHdl) GetMessageHandlerInstanceContext();
- char hdlState;
-
- #pragma unused(bufferOptions);
-
- // Lock the buffer group.
-
- hdlState = HGetState((Handle) buffGrpHdl);
- HLockHi((Handle) buffGrpHdl);
-
-
- // While there's no error, and more data to store, process data.
-
- while (!anErr && (dataLeftToStore > 0))
- {
- // Fill the current buffer with data and indicate that the buffer is dirty.
-
- curBuff = (*buffGrpHdl)->curBuff;
- buffPtr = &(*buffGrpHdl)->buff[curBuff];
-
- while ((dataLeftToStore > 0) && (buffPtr->curOffset < (*buffGrpHdl)->bufferSize))
- {
- // Move the data to our buffer.
-
- buffPtr->printBuffer.data[buffPtr->curOffset] = *pData;
- ++(buffPtr->curOffset);
- ++pData;
- --dataLeftToStore;
- }
-
- buffPtr->bufferIsDirty = true;
-
-
- // If dataLeftToStore > 0, it means that we've filled the current buffer,
- // and we need another. Find a free one.
-
- if (dataLeftToStore > 0)
- {
- foundAFreeBuffer = false;
-
- // If we can find another buffer that's not dirty, we've found
- // a buffer we can store data in. By specifying numBuffers -1
- // below, we avoid checking the current buffer, which we know
- // is dirty.
-
- for (idx = 0; idx < ((*buffGrpHdl)->numBuffers -1); idx++)
- {
- // Search up from the last buffer we checked,
- // wrapping around if necessary.
-
- ++curBuff;
- if (curBuff >= (*buffGrpHdl)->numBuffers)
- curBuff = 0;
-
- buffPtr = &(*buffGrpHdl)->buff[curBuff];
-
- if (!buffPtr->bufferIsDirty)
- {
- foundAFreeBuffer = true;
- break;
- }
- }
-
- // If there are no free buffers, flush them all and use
- // buffer 0.
-
- if (!foundAFreeBuffer)
- {
- anErr = FlushBuffers(buffGrpHdl);
- curBuff = 0;
- }
-
- // Whatever our current buffer is, store it in our buffer
- // structure.
-
- (*buffGrpHdl)->curBuff = curBuff;
- }
- }
-
- // Restore the state of the buffer group handle.
-
- HSetState((Handle) buffGrpHdl, hdlState);
- return anErr;
- }
-
-
- /* -----------------------------------------------------------------------
-
- SD_FreeBuffer is an override for the gxFreeBuffer message. You only
- need to override this message if you're doing asynchronous I/O. Since
- we're not, this is only here as a reminder for you. It does nothing
- but forward the message to the default implementation of gxFreeBuffer.
-
- ----------------------------------------------------------------------- */
-
- OSErr SD_FreeBuffer(gxPrintingBuffer *theBuffer)
- {
- return Forward_GXFreeBuffer(theBuffer);
- }
-
-
- /* -----------------------------------------------------------------------
-
- WriteFileData is a routine that writes the passed data to a file whose
- reference ID is stored in our global data.
-
- ----------------------------------------------------------------------- */
-
- OSErr WriteFileData(void *dataBuffer, long dataLength)
- {
- long amtToWrite = dataLength;
- DriverGlobalsHdl drvrGlobalsHdl = GetDriverGlobals();
-
- // Write some data to our file.
-
- return FSWrite((*drvrGlobalsHdl)->curFileRefNum, &amtToWrite, dataBuffer);
- }
-
-
- /* -----------------------------------------------------------------------
-
- SD_WriteData is an override for gxWriteData. Here, we flush our custom
- buffers and then write the passed data, if any, to the output file
- using our custom I/O routine, WriteFileData.
-
- ----------------------------------------------------------------------- */
-
- OSErr SD_WriteData(Ptr data, long length)
- {
- OSErr anErr;
- register BufferGroupHdl buffGrpHdl = (BufferGroupHdl) GetMessageHandlerInstanceContext();
-
- // Flush the buffers, then do the actual write.
-
- anErr = FlushBuffers(buffGrpHdl);
-
- if (!anErr && (data != nil) && (length > 0))
- anErr = WriteFileData(data, length);
-
- return anErr;
- }
-
-
- /* -----------------------------------------------------------------------
-
- SD_DumpBuffer is an override for gxDumpBuffer. Here, we write the
- passed data to the output file using our custom I/O routine,
- WriteFileData.
-
- ----------------------------------------------------------------------- */
-
- OSErr SD_DumpBuffer(gxPrintingBuffer *theBuffer)
- {
- if (theBuffer->size != 0)
- return WriteFileData(theBuffer->data, theBuffer->size);
- else
- return noErr;
- }
-
-
- /* -----------------------------------------------------------------------
-
- SD_ImageJob is an override for gxImageJob. Here, we create and
- initialize global data that we'll use during imaging.
-
- ----------------------------------------------------------------------- */
-
- OSErr SD_ImageJob(gxSpoolFile theSpoolFile, long *closeOptions)
- {
- OSErr anErr;
- FSSpec anFSSpec;
- short vRefNum;
- long dirID, itemSize;
- gxJobInfo jobInfo;
- Str255 fileName;
- DriverGlobalsHdl drvrGlobalsHdl;
-
- // Create and store a handle for our global data.
-
- anErr = CreateAndStoreGlobals(&drvrGlobalsHdl);
-
-
- // Now, do some more initialization for the first file we'll write to.
-
- if (!anErr)
- {
- // Determine the name of this document, and append ", Page " to it.
- // We'll use this when we create PICT files. Again, the string
- // should really come from a resource file, for localization
- // reasons.
-
- itemSize = sizeof(gxJobInfo);
- anErr = GetCollectionItem(GXGetJobCollection(GXGetJob()),
- gxJobTag, gxPrintingTagID,
- &itemSize, &jobInfo);
-
- nrequire(anErr, GetCollectionItemFailed);
-
- if (jobInfo.documentName[0] > 22) // If necessary, crop file name so we
- jobInfo.documentName[0] = 22; // have room for our page # stuff.
-
- BlockMove(&jobInfo.documentName[1], &fileName[1], (long) jobInfo.documentName[0]);
- BlockMove(", Page ", &fileName[jobInfo.documentName[0] +1], 7);
-
- // Now make an FSSpec for this file.
-
- FindFolder(kOnSystemDisk, kDesktopFolderType, kCreateFolder, &vRefNum, &dirID);
- fileName[0] = jobInfo.documentName[0] +7;
- FSMakeFSSpec(vRefNum, dirID, fileName, &anFSSpec);
- BlockMove(&anFSSpec, &(*drvrGlobalsHdl)->fileLocation, sizeof(FSSpec));
-
- // Set the number of pages we've imaged to 0.
-
- (*drvrGlobalsHdl)->pagesImaged = 0;
-
- // With our global data initialized, it's time to forward the
- // gxImageJob message so that the job is processed.
-
- anErr = Forward_GXImageJob(theSpoolFile, closeOptions);
-
- // All done imaging! Close the last file, if it's still open,
- // and flush the volume so that we get the changes out to disk
- // faster.
-
- if ((*drvrGlobalsHdl)->curFileRefNum)
- FSClose((*drvrGlobalsHdl)->curFileRefNum);
-
- FlushVol("\p", (*drvrGlobalsHdl)->fileLocation.vRefNum);
-
- GetCollectionItemFailed:
-
- // However we get here, dispose of the global data we allocated above.
-
- DisposeGlobals();
- }
-
- return anErr;
- }
-
-
- /* -----------------------------------------------------------------------
-
- SD_StartSendPage is an override for gxStartSendPage. Here, we close
- the current file (if any) and open a new one for the next page. This
- way, we're able to create a PICT file for each page of a document.
-
- ----------------------------------------------------------------------- */
-
- OSErr SD_StartSendPage(gxFormat pageFormat)
- {
- OSErr anErr;
- char numStr[11], maxChars, nextChar;
- long numLen;
- DriverGlobalsHdl drvrGlobalsHdl = GetDriverGlobals();
-
- #pragma unused(pageFormat);
-
- // Close current file, if any.
-
- HLockHi((Handle) drvrGlobalsHdl);
-
- if ((*drvrGlobalsHdl)->curFileRefNum)
- {
- FSClose((*drvrGlobalsHdl)->curFileRefNum);
- (*drvrGlobalsHdl)->curFileRefNum = nil;
- }
-
- // Bump the number of pages imaged, and use that in the
- // filename for the next page. We started pagesImaged at
- // 0, so the first filename will have a 1 appended to it.
-
- (*drvrGlobalsHdl)->lastYPos = 0;
- ++(*drvrGlobalsHdl)->pagesImaged;
-
- NumToString((*drvrGlobalsHdl)->pagesImaged, numStr);
- numLen = (unsigned long) numStr[0];
- maxChars = 31 -numLen;
-
- if ((*drvrGlobalsHdl)->fileLocation.name[0] > maxChars)
- (*drvrGlobalsHdl)->fileLocation.name[0] = maxChars;
-
- nextChar = (*drvrGlobalsHdl)->fileLocation.name[0] +1;
- BlockMove(&numStr[1], &(*drvrGlobalsHdl)->fileLocation.name[nextChar], numLen);
- (*drvrGlobalsHdl)->fileLocation.name[0] += numLen;
-
-
- // Create a new file for this page, recklessly replacing any
- // existing file with that name.
-
- FSpDelete(&(*drvrGlobalsHdl)->fileLocation);
- anErr = FSpCreate(&(*drvrGlobalsHdl)->fileLocation, kFileCreator, kFileType, smSystemScript);
-
-
- // Open the new file, and write the beginning of the PICT file.
-
- if (!anErr)
- anErr = FSpOpenDF(&(*drvrGlobalsHdl)->fileLocation, fsCurPerm, &(*drvrGlobalsHdl)->curFileRefNum);
-
- if (!anErr)
- anErr = WriteStartOfPICTFile();
-
-
- // Initialize this page's PICT's pixmap's bounds to (0,0,0,0).
-
- (*drvrGlobalsHdl)->pixMapBounds.top = 0;
- (*drvrGlobalsHdl)->pixMapBounds.left = 0;
- (*drvrGlobalsHdl)->pixMapBounds.bottom = 0;
- (*drvrGlobalsHdl)->pixMapBounds.right = 0;
-
-
- // Strip the page number we just added from the file name in our globals.
- // This way, we won't have it when it comes time to set up the file name
- // for the next page.
-
- (*drvrGlobalsHdl)->fileLocation.name[0] -= numLen;
- HUnlock((Handle) drvrGlobalsHdl);
-
-
- // Finally, forward gxStartSendPage so that GX and any overrides can do
- // whatever they need to do.
-
- if (!anErr)
- anErr = Forward_GXStartSendPage(pageFormat);
-
- return anErr;
- }
-
-
- /* -----------------------------------------------------------------------
-
- SD_FinishSendPage is an override for gxFinishSendPage. Here, we
- forward the gxFinishPage message and write out the end of the PICT
- file we created in SD_StartSendPage.
-
- ----------------------------------------------------------------------- */
-
- OSErr SD_FinishSendPage()
- {
- OSErr anErr1, anErr2;
-
- // Forward the gxFinishPage message and write out the
- // remainder of this page's PICT file.
-
- anErr1 = Forward_GXFinishSendPage();
- anErr2 = WriteEndOfPICTFile();
-
- return (anErr1)? anErr1: anErr2;
- }
-
-
- /* -----------------------------------------------------------------------
-
- SD_SetupImageData is an override for gxSetupImageData. Here, we
- forward the gxSetupImageData message and store the resolution for
- the PICTs we'll create.
-
- ----------------------------------------------------------------------- */
-
- OSErr SD_SetupImageData(gxRasterImageDataHdl hImageData)
- {
- OSErr anErr;
- DriverGlobalsHdl drvrGlobalsHdl = GetDriverGlobals();
-
- // Do the default setup.
-
- anErr = Forward_GXSetupImageData(hImageData);
-
- // Set up our PICT resolution based on the information in the
- // gxRasterImageDataHdl that we're passed.
-
- (*drvrGlobalsHdl)->hRes = (*hImageData)->hImageRes;
- (*drvrGlobalsHdl)->vRes = (*hImageData)->vImageRes;
-
- return (anErr);
- }
-
-
- /* -----------------------------------------------------------------------
-
- CreateBuffers is the routine which creates and initializes our custom
- buffers.
-
- ----------------------------------------------------------------------- */
-
- OSErr CreateBuffers()
- {
- OSErr anErr;
- BufferGroupHdl theBuffs;
- long thisBig = sizeof(BufferGroup) +(sizeof(BufferEntry) * (kNumBuffs -1));
-
- // Create one handle for our buffers. Note that this code does not
- // reduce the buffer size based on available memory. That would be
- // a preferable approach.
-
- theBuffs = (BufferGroupHdl) TempNewHandle(thisBig, &anErr);
-
- if (!anErr)
- {
- short idx;
-
- // Initialize the buffer structure and store the buffer group in
- // our instance context so we can get it later.
-
- (*theBuffs)->numBuffers = kNumBuffs;
- (*theBuffs)->bufferSize = kOurBufferSize;
- (*theBuffs)->curBuff = 0;
-
- for (idx = 0; idx < (*theBuffs)->numBuffers; idx++)
- {
- (*theBuffs)->buff[idx].bufferIsDirty = false;
- (*theBuffs)->buff[idx].curOffset = 0;
- }
-
- SetMessageHandlerInstanceContext(theBuffs);
- }
- else;
- // We suck, we didn't downsize our buffers for the available RAM,
- // and now we've failed miserably.
-
- return anErr;
- }
-
-
- /* -----------------------------------------------------------------------
-
- DisposeBuffers is the routine which disposes of our custom buffers.
-
- ----------------------------------------------------------------------- */
-
- OSErr DisposeBuffers()
- {
- Handle bufferGroup = GetMessageHandlerInstanceContext();
-
- // Have we set up them there buffers? Then erradicate 'em.
-
- if (bufferGroup != nil)
- DisposeHandle(bufferGroup);
-
- return noErr;
- }
-
-
- /* -----------------------------------------------------------------------
-
- FlushBuffers is the routine which flushes our custom buffers. To do
- this, it cycles through each one to see if there's data in it. If so,
- it sends gxDumpBuffer for the buffer, followed by gxFreeBuffer.
-
- ----------------------------------------------------------------------- */
-
- OSErr FlushBuffers(BufferGroupHdl buffGrpHdl)
- {
- OSErr anErr = noErr;
- short idx;
- char hdlState;
-
- // Lock the buffer group.
-
- hdlState = HGetState((Handle) buffGrpHdl);
- HLockHi((Handle) buffGrpHdl);
-
- // Send gxDumpBuffer and gxFreeBuffer for each buffer with data in it.
-
- for (idx = 0; idx < (*buffGrpHdl)->numBuffers; idx++)
- {
- if ((*buffGrpHdl)->buff[idx].bufferIsDirty)
- {
- // gxDumpBuffer will look at printbuffer.size to see how much
- // data to write out. Set it to the current offset, which just
- // happens to equal the number of bytes we've stored in the buffer.
-
- (*buffGrpHdl)->buff[idx].printBuffer.size = (*buffGrpHdl)->buff[idx].curOffset;
-
-
- // Send gxDumpBuffer and gxFreeBuffer for this buffer.
-
- anErr = Send_GXDumpBuffer(&(*buffGrpHdl)->buff[idx].printBuffer);
-
- if (!anErr)
- anErr = Send_GXFreeBuffer(&(*buffGrpHdl)->buff[idx].printBuffer);
-
-
- // Clear the buffer's dirty flag and reset its data offset.
-
- (*buffGrpHdl)->buff[idx].bufferIsDirty = false;
- (*buffGrpHdl)->buff[idx].curOffset = 0;
- }
- }
-
- (*buffGrpHdl)->curBuff = 0;
-
- // Restore the state of the buffer group handle.
- HSetState((Handle) buffGrpHdl, hdlState);
-
- return anErr;
- };
-
-
- /* -----------------------------------------------------------------------
-
- WriteStartOfPICTFile is a routine that writes out the start of an
- extended version 2 PICT that only contains a clip and a pixmap. In
- this routine we write out all the data up to the pixmap data. However,
- since we won't know things like the bounds and rowbytes until later,
- we simply write out zeroes now, and update everything when we're done
- imaging this page. We do the updating in the routine
- WriteEndOfPICTFile.
-
- ----------------------------------------------------------------------- */
-
- OSErr WriteStartOfPICTFile()
- {
- OSErr anErr;
- Ptr dataPtr;
-
- // We need to write out the 512 unused bytes that every PICT file
- // contains, plus 122 bytes that comprise the header and information
- // that precedes the pixel data in our pixmap. Since we do this at
- // the start of the page, when SD_DumpBuffer and SD_WriteData write
- // data to the file, they'll actually be filling out the pixel data
- // in our PICT's pixmap.
- //
- // Anyway, create a clear pointer that's big enough to hold all the
- // data that precedes our pixmap's pixels. If there are no errors,
- // write it out via our gxBufferData override. When done, dispose
- // of the pointer we used.
-
- dataPtr = NewPtrClear(512 +122);
-
- if (!(anErr = MemError()))
- {
- anErr = Send_GXBufferData(dataPtr, 512 +122, gxNoBufferOptions);
- DisposePtr(dataPtr);
- }
-
- return anErr;
- }
-
-
- /* -----------------------------------------------------------------------
-
- WriteEndOfPICTFile is a routine that writes out the end of an
- extended version 2 PICT that only contains a clip and a pixmap. It
- also updates the beginning of the PICT, with information about the
- pixmap's bounds and so forth. The beginning of the PICT was written
- out with the WriteStartOfPICTFile routine.
-
- Writing out the end of the PICT simply involves writing out the end-
- of-PICT opCode 0x00FF. Most of the work done in this routine has to
- do with updating the start-of-PICT data that we already wrote out.
-
- ----------------------------------------------------------------------- */
-
- OSErr WriteEndOfPICTFile()
- {
- OSErr anErr;
- fixed hRes, vRes, hResScale, vResScale;
- short finalPictData;
- short initialPictData[61], curFileRefNum;
- long index = 0, pictSize;
- Rect drawRect, a72dpiDrawRect;
- DriverGlobalsHdl drvrGlobalsHdl = GetDriverGlobals();
-
- // Get the horizontal and vertical resolutions that we imaged
- // at, along with the scaling necessary to apply to 72 dpi
- // viewing rectangles for this image.
-
- hRes = (*drvrGlobalsHdl)->hRes;
- vRes = (*drvrGlobalsHdl)->vRes;
- hResScale = FixRatio(hRes >>16, 72);
- vResScale = FixRatio(vRes >>16, 72);
-
- // Get the pixmap's native bounds, and calculate the correct
- // viewing rectangle for 72 dpi. We pin the top/left corner
- // of each rectangle to 0,0 for convenience.
-
- drawRect = (*drvrGlobalsHdl)->pixMapBounds;
- OffsetRect(&drawRect, -drawRect.left, -drawRect.top);
- a72dpiDrawRect.top = a72dpiDrawRect.left = 0;
- a72dpiDrawRect.bottom = (FixMul(ff(drawRect.bottom), vResScale) >>16);
- a72dpiDrawRect.right = (FixMul(ff(drawRect.right), hResScale) >>16);
-
- // Flush our buffers. (Yes, since we're doing our own buffer
- // management, we could just call FlushBuffers, but this is how
- // you'd do it otherwise.)
-
- anErr = Send_GXWriteData(nil, 0);
- nrequire(anErr, FlushBuffersFailed);
-
- // Get the current file's refNum. Since we flushed the buffers,
- // we can go back and see how big the PICT is. Do so.
-
- curFileRefNum = (*drvrGlobalsHdl)->curFileRefNum;
- anErr = GetEOF(curFileRefNum, &pictSize);
- nrequire(anErr, GetEOFFailed);
-
- // If necessary, add a $00 to word align the endPict opcode.
-
- if ((pictSize & 1) != 0)
- {
- finalPictData = 0;
- anErr = Send_GXWriteData((Ptr) &finalPictData, 1);
- nrequire(anErr, WordAlignFailed);
- ++pictSize;
- }
-
- // Write the endPict opcode.
-
- finalPictData = 0x00FF;
- anErr = Send_GXWriteData((Ptr) &finalPictData, 2);
- nrequire(anErr, SendFinalDataFailed);
-
- // Now, we're ready to update the information that precedes
- // the pixmap data. Set our file position to 512 bytes from
- // the start. That puts us just past the obsolete PICT header
- // that we're required to include.
-
- anErr = SetFPos(curFileRefNum, fsFromStart, 512);
- nrequire(anErr, SetFPosFailed);
-
- // Store the low word of picsize.
-
- initialPictData[index] = pictSize & 0xFFFF;
- ++index;
-
- // Store the 72 dpi picFrame.
-
- initialPictData[index] = a72dpiDrawRect.top;
- ++index;
- initialPictData[index] = a72dpiDrawRect.left;
- ++index;
- initialPictData[index] = a72dpiDrawRect.bottom;
- ++index;
- initialPictData[index] = a72dpiDrawRect.right;
- ++index;
-
- // Store the pict version opcode ($0011).
-
- initialPictData[index] = 0x0011;
- ++index;
-
- // Store the pict version ($02FF).
-
- initialPictData[index] = 0x02FF;
- ++index;
-
- // Store the header opcode ($0C00).
-
- initialPictData[index] = 0x0C00;
- ++index;
-
- // Store the header version (-2).
-
- initialPictData[index] = -2;
- ++index;
-
- // Store the reserved word (0).
-
- initialPictData[index] = 0;
- ++index;
-
- // Store the native horizontal resolution (fixed) of the source data.
-
- initialPictData[index] = hRes >>16;
- ++index;
- initialPictData[index] = hRes & 0xFFFF;
- ++index;
-
- // Store the native vertical resolution (fixed) of the source data.
-
- initialPictData[index] = vRes >>16;
- ++index;
- initialPictData[index] = vRes & 0xFFFF;
- ++index;
-
- // Store the native source rectangle.
-
- initialPictData[index] = drawRect.top;
- ++index;
- initialPictData[index] = drawRect.left;
- ++index;
- initialPictData[index] = drawRect.bottom;
- ++index;
- initialPictData[index] = drawRect.right;
- ++index;
-
- // Store the reserved longword (0L).
-
- initialPictData[index] = 0;
- ++index;
- initialPictData[index] = 0;
- ++index;
-
- // Store the clip opcode (1).
-
- initialPictData[index] = 1;
- ++index;
-
- // Store the size of the clip region data (10).
-
- initialPictData[index] = 10;
- ++index;
-
- // Store the clip rectangle.
-
- initialPictData[index] = drawRect.top;
- ++index;
- initialPictData[index] = drawRect.left;
- ++index;
- initialPictData[index] = drawRect.bottom;
- ++index;
- initialPictData[index] = drawRect.right;
- ++index;
-
- // Store the opBitsRect opcode ($009A).
-
- initialPictData[index] = 0x009A;
- ++index;
-
- // Store the pixmap's baseAddr placeholder (always $000000FF).
-
- initialPictData[index] = 0x0000;
- ++index;
- initialPictData[index] = 0x00FF;
- ++index;
-
- // Store the rowBytes (high bit must be set for a pixmap).
-
- initialPictData[index] = (*drvrGlobalsHdl)->pixMapRowBytes | 0x8000;
- ++index;
-
- // Store the pixmap bounds at source resolution.
-
- initialPictData[index] = drawRect.top;
- ++index;
- initialPictData[index] = drawRect.left;
- ++index;
- initialPictData[index] = drawRect.bottom;
- ++index;
- initialPictData[index] = drawRect.right;
- ++index;
-
- // Store the pixmap version (0).
-
- initialPictData[index] = 0;
- ++index;
-
- // Store the pixmap packing type (2 == we dropped pad bytes).
-
- initialPictData[index] = 2;
- ++index;
-
- // Store the packing size (0L).
-
- initialPictData[index] = 0;
- ++index;
- initialPictData[index] = 0;
- ++index;
-
- // Store the horizontal resolution (fixed) of the source data.
-
- initialPictData[index] = hRes >>16;
- ++index;
- initialPictData[index] = hRes & 0xFFFF;
- ++index;
-
- // Store the vertical resolution (fixed) of the source data.
-
- initialPictData[index] = vRes >>16;
- ++index;
- initialPictData[index] = vRes & 0xFFFF;
- ++index;
-
- // Store the pixelType (direct == 16).
-
- initialPictData[index] = 16;
- ++index;
-
- // Store the pixelSize (32 (packed to 24) bits per pixel).
-
- initialPictData[index] = 32;
- ++index;
-
- // Store the pixel component count (3).
-
- initialPictData[index] = 3;
- ++index;
-
- // Store the pixel component size (8).
-
- initialPictData[index] = 8;
- ++index;
-
- // Store the offset to next plane (0).
-
- initialPictData[index] = 0;
- ++index;
- initialPictData[index] = 0;
- ++index;
-
- // Store the ctSeed (0L).
-
- initialPictData[index] = 0;
- ++index;
- initialPictData[index] = 0;
- ++index;
-
- // Store the ctFlags (0).
-
- initialPictData[index] = 0;
- ++index;
-
- // Store the ctSize (-1 == 0 entries. Unused for direct pixmaps anyway).
-
- initialPictData[index] = -1;
- ++index;
-
- // Store the source rectangle at source resolution.
-
- initialPictData[index] = drawRect.top;
- ++index;
- initialPictData[index] = drawRect.left;
- ++index;
- initialPictData[index] = drawRect.bottom;
- ++index;
- initialPictData[index] = drawRect.right;
- ++index;
-
- // Store the destination rectangle at 72 dpi.
-
- initialPictData[index] = a72dpiDrawRect.top;
- ++index;
- initialPictData[index] = a72dpiDrawRect.left;
- ++index;
- initialPictData[index] = a72dpiDrawRect.bottom;
- ++index;
- initialPictData[index] = a72dpiDrawRect.right;
- ++index;
-
- // Store the transfer mode (ditherCopy).
-
- initialPictData[index] = ditherCopy;
- ++index;
-
- // The number of bytes we've got to write is index *2 (since
- // we bumped index at every word we stored). Empirically, this
- // comes out to 122 bytes, which explains the 122 bytes in
- // WriteStartOfPICTFile and the 61 words allocated for
- // initialPictData. If you change the data that's written into
- // this file, make sure you update those two values!!
- //
- // Write out the updated data.
-
- index *= 2;
- anErr = FSWrite(curFileRefNum, &index, initialPictData);
-
- SetFPosFailed:
- SendFinalDataFailed:
- WordAlignFailed:
- GetEOFFailed:
- FlushBuffersFailed:
-
- return anErr;
- }
-
-
-